package org.jeecg.modules.iot.mqtt.server.service.processor.control;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.jeecg.modules.iot.model.control.TaitModbusControllerResponse;
import org.springframework.stereotype.Component;

@Component("taitModbusControllerParser")
public class TaitModbusControlParser {

    /**
     * 解析泰比特MODBUS协议的控制器数据
     *
     * @param data MODBUS响应数据，例如："01 03 1A 42 54 31 30 36 30 30 32 34 33 30 4C 54 30 30 32 31 30 37 33 31 30 30 31 00 00 E3 82"
     * @return 解析后的控制器数据
     */

    public TaitModbusControllerResponse parseControllerData(byte[] data, Integer startAdress) {
        /*解析控制器*/
        System.out.println("解析控制器");
        int startingAddress = 0xA100; // 控制器的起始地址为 0xA100
        if (startAdress!=null){
            startingAddress=startAdress;
        }
        // 使用 Unpooled.wrappedBuffer 创建 ByteBuf
        ByteBuf buf = Unpooled.wrappedBuffer(data);

        // 创建一个 TaitModbusControllerResponse 对象，用于存储所有解析到的数据
        TaitModbusControllerResponse response = new TaitModbusControllerResponse();

        // 读取从机地址
        if (buf.readableBytes() < 1) {
            return null;
        }
        int slaveAddress = buf.readByte() & 0xFF;
        if (buf.readableBytes() < 1) {
            return null;
        }
        // 读取功能码
        int functionCode = buf.readByte() & 0xFF;
        if (buf.readableBytes() < 1) {
            return null;
        }
        // 读取数据字节数
        int dataLength = buf.readByte() & 0xFF;

        if (buf.readableBytes() < dataLength) {
            return null;
        }
        byte[] dataArray = new byte[dataLength];
        buf.readBytes(dataArray);

        // 读取CRC校验码
        byte crcHigh = buf.readByte();
        byte crcLow = buf.readByte();

        // 计算校验码
        byte[] calculatedCRC = calculateCRC16(data, 0, data.length - 2);

        // 比较计算得到的校验码和数据包中的校验码
        if (calculatedCRC[0] == crcHigh && calculatedCRC[1] == crcLow) {
            // 校验码匹配，数据包完整

            // 解析数据包并将数据存入 response 对象
            parseDataPacket(response, slaveAddress, functionCode, dataArray, dataLength, startingAddress);
        } else {
            // 校验码不匹配，数据包错误
            System.err.println("CRC校验失败！");
        }

        // 释放 ByteBuf
        buf.release();

        // 返回解析后的 TaitModbusControllerResponse 对象
        return response;
    }

    /**
     * 解析单个数据包并将数据存入 response 对象
     *
     * @param response       TaitModbusControllerResponse 对象，用于存储解析到的数据
     * @param packetData     数据包字节数组
     * @param startingAddress 数据起始地址
     */
    private void parseDataPacket(TaitModbusControllerResponse response, int slaveAddress, int functionCode, byte[] dataBuf, int dataLength, int startingAddress) {
        // 根据功能码解析数据
        if (slaveAddress == 0x01) {
            response.setDeviceId(asciiToString(dataBuf));
        } else if (slaveAddress == 0x03 || slaveAddress == 0x04) { // 根据文档，从机地址 0x03 和 0x04 都可能是控制器
            if (functionCode == 0x03) {
                // 读多个寄存器,解析数据
                ByteBuf buf = Unpooled.wrappedBuffer(dataBuf);
                parseDataByAddress(response, buf, startingAddress, dataLength, dataBuf.length);
                buf.release();

            }
        }
    }

    private byte[] calculateCRC16(byte[] data, int start, int len) {
        int crc = 0xFFFF;
        for (int i = start; i < start + len; i++) {
            crc ^= (data[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                if ((crc & 0x0001) != 0) {
                    crc >>= 1;
                    crc ^= 0xA001;
                } else {
                    crc >>= 1;
                }
            }
        }
        return new byte[]{(byte) (crc & 0xFF), (byte) ((crc >> 8) & 0xFF)};
    }

    private void parseDataByAddress(TaitModbusControllerResponse response, ByteBuf dataBuf, int startingAddress, int dataLength, int totalLength) {
        // 计算起始地址偏移量
        int offset = (startingAddress - 0xA100) * 2; // 每个寄存器占2个字节，并且起始地址为 0xA100

        // 如果起始地址偏移量超出数据范围，则不进行解析
        if (offset < 0 || offset >= totalLength) {
            return;
        }

        // 从偏移量开始读取数据
        dataBuf.readerIndex(offset);

        // 解析数据，直到数据读取完毕
        outer:
        while (dataBuf.readerIndex() < totalLength) {
            int currentAddress = startingAddress + (dataBuf.readerIndex() - offset) / 2;
            System.out.println("当前地址"+currentAddress+"解析成"+decimalToHex(currentAddress));
            switch (currentAddress) {
                case 0xA100:
                    // 读取 16 位寄存器值
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    int registerValue = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA100",registerValue);
                    // 解析控制器当前工作模式
                    int mode = registerValue >> 14; // 读取高两位 (Bit15-Bit14)
                    switch (mode) {
                        case 0b00:
                            response.setWorkMode("纯助力");
                            break;
                        case 0b01:
                            response.setWorkMode("纯电动");
                            break;
                        case 0b11:
                            response.setWorkMode("混合");
                            break;
                        default:
                            response.setWorkMode("未知");
                            break;
                    }

                    // 解析启动模式
                    int startMode = (registerValue >> 13) & 0x01; // 读取 Bit13
                    response.setStartMode(startMode == 0 ? "0" : "1");

                    // 解析非零启动模式下关闭转把的等待时间
                    int throttleOffDelay = (registerValue >> 10) & 0x07; // 读取 Bit4~Bit2
                    response.setThrottleOffDelay(throttleOffDelay);

                    // 解析锁电机信号
                    int motorLockSignal = (registerValue >> 9) & 0x01; // 读取 Bit1
                    response.setMotorLockSignal(motorLockSignal == 1 ? "上锁" : "解锁");

                    // 解析动力禁用使能
                    int powerDisable = (registerValue >> 8) & 0x01; // 读取 Bit0
                    response.setPowerDisable(powerDisable == 1 ? "不输出动力" : "输出动力");

                    // 读取低位 Uint8，国标速度或设定默认时速
                    response.setSpeedLimit(String.valueOf(dataBuf.readUnsignedByte()));
                    break;
                case 0xA101:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 解析电机控制器车辆故障
                    int vehicleFaults = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA101",vehicleFaults);
                    response.setVehicleFaults(vehicleFaults);

                    // 解析控制器状态的各个bit位
                    response.setHallFault(isBitSet(vehicleFaults, 15));
                    response.setThrottleFault(isBitSet(vehicleFaults, 14));
                    response.setBrakeFault(isBitSet(vehicleFaults, 13));
                    response.setAssistFault(isBitSet(vehicleFaults, 12));
                    response.setControllerFault(isBitSet(vehicleFaults, 11));
                    response.setMotorFault(isBitSet(vehicleFaults, 10));
                    response.setUnderVoltageProtection(isBitSet(vehicleFaults, 9));
                    response.setOverVoltageProtection(isBitSet(vehicleFaults, 8));
                    response.setOverCurrentProtection(isBitSet(vehicleFaults, 7));
                    response.setButtonFault(isBitSet(vehicleFaults, 6));
                    response.setTailLightFault(isBitSet(vehicleFaults, 5));
                    response.setPassengerSensorFault(isBitSet(vehicleFaults, 4));
                    // bit3~bit0 未定义，暂不解析

                    break;
                case 0xA102:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 读取 16 位寄存器值
                    int a102Value = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA102",a102Value);

                    // Bit15-Bit7: 备用 (无需解析)

                    // Bit6: 载人检测状态
                    response.setPassengerDetection((a102Value & 0x40) != 0);

                    // Bit5: 防飞车保护状态
                    response.setAntiFlyProtection((a102Value & 0x20) != 0);

                    // Bit4: 负载超重状态
                    response.setOverloadDetection((a102Value & 0x10) != 0);

                    // Bit3: 空车值标定
                    response.setIdleCalibration((a102Value & 0x08) != 0);

                    // Bit2: 堵转保护状态
                    response.setStallProtection((a102Value & 0x04) != 0);

                    // Bit1: 电机运行状态
                    response.setMotorRunning((a102Value & 0x02) != 0);

                    // Bit0: 车辆刹车状态
                    response.setBrakeActivated((a102Value & 0x01) != 0);
                    break;
                case 0xA103:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 假设 wheelDiameterUnit 是一个配置项或参数，值为 "cm" 或 "inch"
                    String wheelDiameterUnit = "cm"; // 默认单位为厘米

                    // Byte1 高字节: 轮径
                    int wheelDiameter = dataBuf.readUnsignedByte();

                    if (wheelDiameterUnit.equals("inch")) {
                        // 如果单位为寸，转换为厘米
                        wheelDiameter = (int) Math.round(wheelDiameter * 2.54);
                    }
                    response.setWheelDiameter(wheelDiameter);

                    // Byte0 低字节: 控制器上报事件类型
                    int eventType = dataBuf.readUnsignedByte();

                    printRegisterValue("0xA103",wheelDiameter+eventType);

                    // 解析事件类型中的 "一键还车" 标志位 (bit7)
                    boolean oneClickReturnPressed = (eventType & 0x80) != 0; // 检查bit7是否为1
                    response.setOneClickReturnPressed(oneClickReturnPressed);
                    break;
                case 0xA104:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 单次里程 (单位: 米) 或预留
                    int singleTripMileage = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA104",singleTripMileage);
                    response.setSingleTripMileage(singleTripMileage);
                    break;
                case 0xA105:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 刹车累计次数 (本次上电)
                    int totalBrakeCount = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA105",totalBrakeCount);
                    response.setTotalBrakeCount(totalBrakeCount);
                    break;
                case 0xA106:
                    if (dataBuf.readableBytes() < 4) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 车辆总里程
                    long  mileage = dataBuf.readUnsignedInt();

                    response.setTotalMileage(mileage);
                    break;
                case 0xA108:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 车辆霍尔0.5s变化个数 (送中控和仪表)
                    int hallPulseCount = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA108",hallPulseCount);
                    response.setHallPulseCount(hallPulseCount);
                    break;
                case 0xA109:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 极对数
                    int polePairs = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA109",polePairs);
                    response.setPolePairs(polePairs);
                    break;
                case 0xA10A:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 电机控制器尾灯闪烁使能 (高字节)
                    int tailLightEnable = dataBuf.readUnsignedByte();
                    boolean isTailLightEnabled = (tailLightEnable & 0x01) != 0; // 检查bit0
                    response.setTailLightEnabled(isTailLightEnabled);

                    // 电机控制器尾灯闪烁次数 (低字节)
                    int tailLightBlinkCount = dataBuf.readUnsignedByte();

                    printRegisterValue("0xA10A",tailLightEnable+tailLightBlinkCount);
                    response.setTailLightBlinkCount(tailLightBlinkCount);
                    break;
                case 0xA10B:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 电机控制器尾灯闪烁灭灯时间 (单位: 秒, 高字节)
                    int tailLightOffTime = dataBuf.readUnsignedByte();
                    response.setTailLightOffTime(tailLightOffTime);

                    // 电机控制器尾灯闪烁亮灯时间 (单位: 秒, 低字节)
                    int tailLightOnTime = dataBuf.readUnsignedByte();
                    printRegisterValue("0xA10B",tailLightOffTime+tailLightOnTime);

                    response.setTailLightOnTime(tailLightOnTime);
                    break;
                case 0xA10C:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 电池锁控制和状态
                    int lockControlAndStatus = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA10C",lockControlAndStatus);
                    // 高字节 - 锁控制
                    int lockControl = (lockControlAndStatus >> 8) & 0xFF;
                    int lockAction = (lockControl >> 6) & 0x03;
                    int lockDriveTime = lockControl & 0x0F;

                    // 根据 lockAction 设置锁操作
                    String lockActionStr;
                    if (lockAction == 0x02) {
                        lockActionStr = "UNLOCK";
                    } else if (lockAction == 0x01) {
                        lockActionStr = "LOCK";
                    } else {
                        lockActionStr = "INVALID";
                    }
                    response.setBatteryLockAction(lockActionStr);

                    // 设置锁驱动时间
                    if (lockDriveTime > 0) {
                        response.setBatteryLockDriveTime(lockDriveTime * 500); // 单位转换为毫秒
                    } else {
                        response.setBatteryLockDriveTime(500); // 使用默认值
                    }

                    // 低字节 - 锁状态
                    int lockStatus = lockControlAndStatus & 0xFF;
                    boolean isLocked = (lockStatus & 0x01) == 1; // 修改此处：1: 高电平 (锁舌弹出), 0: 低电平 (锁舌缩回)
                    response.setBatteryLocked(isLocked);
                    break;
                case 0xA10D:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 同步电池电压类型
                    int batteryVoltageType = dataBuf.readUnsignedByte();
                    response.setBatteryVoltageType(batteryVoltageType);

                    // 控制器限流值
                    int controllerCurrentLimit = dataBuf.readUnsignedByte();
                    printRegisterValue("0xA10D",batteryVoltageType+controllerCurrentLimit);
                    response.setControllerCurrentLimit(controllerCurrentLimit);
                    break;

                case 0xA10E:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 中控配置控制器功能
                    int configValue = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA10E",configValue);


                    // Bit0: 国标/解速
                    response.setSpeedLimitEnabled((configValue & 0x01) == 1);

                    // Bit1: 联动功能
                    response.setLinkageEnabled((configValue & 0x02) != 0);

                    // Bit2: 备用

                    // Bit3: EABS
                    response.setEabsEnabled((configValue & 0x08) != 0);

                    // Bit4-Bit6: 停车进入 P 档时间
                    int parkingToPTimeValue = (configValue >> 4) & 0x07;
                    int parkingToPTime = 0; // 默认关闭功能
                    switch (parkingToPTimeValue) {
                        case 1:
                            parkingToPTime = 10;
                            break;
                        case 3:
                            parkingToPTime = 30;
                            break;
                        case 6:
                            parkingToPTime = 60;
                            break;
                        case 7:
                            parkingToPTime = 130;
                            break;
                    }
                    /*解-p*/
                    response.setParkingToPTime(parkingToPTime);

                    // Bit7: 防陡坡
                    response.setSlopePreventionEnabled((configValue & 0x80) != 0);

                    // Bit8: TCS
                    response.setTcsEnabled((configValue & 0x100) != 0);

                    // Bit9-Bit10: 启动档位
                    int startGear = (configValue >> 9) & 0x03;
                    response.setStartGear(startGear);

                    // Bit11-Bit15: 软启动等级
                    response.setSoftStartLevel((configValue >> 11) & 0x1F);
                    break;

                case 0xA10F:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 车辆欠压保护电压
                    int undervoltageProtectionVoltage = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA10F",undervoltageProtectionVoltage);
                    double undervoltageProtectionVoltageValue = undervoltageProtectionVoltage * 0.1; // 单位转换为伏特
                    response.setUndervoltageProtectionVoltage(undervoltageProtectionVoltageValue);
                    break;
                case 0xA110:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 其他配置
                    int otherConfigValue = dataBuf.readUnsignedShort();
                    printRegisterValue("0xA110",otherConfigValue);
                    // Bit0-Bit3: EABS 强度
                    int eabsStrength = otherConfigValue & 0x000F;
                    response.setEabsStrength(eabsStrength);

                    // Bit4-Bit7: 刹车能量回收强度 (中控配置)
                    int regenerativeBrakingStrength = (otherConfigValue >> 4) & 0x000F;
                    response.setRegenerativeBrakingStrength(regenerativeBrakingStrength);

                    // Bit8-Bit14: 刹车能量回收 SOC 条件
                    int regenerativeBrakingSocCondition = (otherConfigValue >> 8) & 0x007F;
                    response.setRegenerativeBrakingSocCondition(regenerativeBrakingSocCondition);

                    // Bit15: 国标/解速
                    boolean nationalStandardSpeedLimit = (otherConfigValue & 0x8000) != 0;
                    response.setNationalStandardSpeedLimit(nationalStandardSpeedLimit);
                    break;

                case 0xA111:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 刹车累计次数

                   int sc= dataBuf.readUnsignedShort();
                    printRegisterValue("0xA111",sc);
                    response.setTotalBrakeCount(sc);
                    break;

                case 0xA112:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 累计刹车时长
                    int scTime=dataBuf.readUnsignedShort();
                    printRegisterValue("0xA111",scTime);
                    response.setTotalBrakeDuration(scTime);
                    break;

                case 0xA113:
                    if (dataBuf.readableBytes() < 2) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 一档和二档速度百分比
                    response.setGear1Percentage(dataBuf.readUnsignedByte());
                    response.setGear2Percentage(dataBuf.readUnsignedByte());
                    break;



                case 0xA114:
                    if (dataBuf.readableBytes() < 24) {
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 0xA114-0xA11D 备用，跳过 24 字节
                    dataBuf.skipBytes(24);
                    break;

                case 0xA11E:
                    if (dataBuf.readableBytes() < 24) { // 检查 24 个字节的长度
                        System.err.println("数据长度不足");
                        break outer;
                    }
                    // 控制器 ID 序列号 (12 * Uint16)
                    for (int i = 0; i < 12; i++) {
                        response.setControllerIdSerialNumber(i, dataBuf.readUnsignedShort());
                    }
                    break;

                default:
                    // 未知地址，跳过相应字节数
                    dataBuf.skipBytes(2); // 每个寄存器占2个字节
                    break;
            }
        }
    }

    /**
     * 判断一个整数的指定位是否为1
     *
     * @param value 整数
     * @param bit  位索引，从0开始
     * @return 如果指定位为1，则返回true，否则返回false
     */
    private boolean isBitSet(int value, int bit) {
        return (value & (1 << bit)) != 0;
    }

    private String asciiToString(byte[] ascii) {
        StringBuilder sb = new StringBuilder();
        for (byte b : ascii) {
            sb.append((char) b);
        }
        return sb.toString().trim();
    }


    public static void printRegisterValue( String address,int registerValue) {

        // 分高八位和低八位
        int highByte = (registerValue >> 8) & 0xFF;
        int lowByte = registerValue & 0xFF;

        // 将高八位和低八位分别转换为十六进制字符串
        String highHexString = String.format("%02X", highByte);
        String lowHexString = String.format("%02X", lowByte);

        // 将 registerValue 转换为二进制字符串
        String binaryString = String.format("%16s", Integer.toBinaryString(registerValue)).replace(' ', '0');

        // 打印结果
        System.out.println("地址"+address+"解析-------十六进制: " + highHexString + " " + lowHexString+"二进制: " + binaryString.substring(0, 8) + " " + binaryString.substring(8)+" 十进制: "+highByte +" "+  lowByte);

    }
    /**
     * 将十六进制字符串转换为字节数组
     *
     * @param hexString 十六进制字符串
     * @return 字节数组
     */
    private byte[] hexStringToByteArray(String hexString) {
        // 移除空格
        hexString = hexString.replaceAll("\\s+", "");

        // 检查字符串长度
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("Invalid hexadecimal string");
        }

        // 创建字节数组
        byte[] bytes = new byte[hexString.length() / 2];

        // 转换字符串为字节数组
        for (int i = 0; i < hexString.length(); i += 2) {
            bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }

        return bytes;
    }

    public static void main(String[] args) {
        // 示例数据
        String dataStr = "01 03 1A 42 54 31 30 36 30 30 32 34 33 30 4C 54 30 30 32 31 30 37 33 31 30 30 31 00 00 E3 82";

        String[] dataArray = dataStr.split(" ");
        byte[] data = new byte[dataArray.length];
        for (int i = 0; i < dataArray.length; i++) {
            data[i] = (byte) Integer.parseInt(dataArray[i], 16);
        }

        // 创建TaitModbusControllerParser对象
        TaitModbusControlParser parser = new TaitModbusControlParser();

        // 解析数据
        TaitModbusControllerResponse response = parser.parseControllerData(data,null);

        // 打印解析结果
        System.out.println(response.toString());
    }

    public static String[] hexStringToArray(String hexString) {
        // 检查字符串长度是否为偶数
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("Hex string length must be even.");
        }

        // 创建数组，长度为字符串长度的一半
        String[] dataArray = new String[hexString.length() / 2];

        // 循环遍历字符串，每两位转换为一个字符串元素
        for (int i = 0; i < hexString.length(); i += 2) {
            dataArray[i / 2] = hexString.substring(i, i + 2);
        }

        return dataArray;
    }
    public static String decimalToHex(int decimal) {
        return "0x" + Integer.toHexString(decimal).toUpperCase();
    }
}